//
// Created by DonAzufre on 24-5-18.
//

#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"

#include <map>
#include <string>

using namespace llvm;

namespace {
    using namespace std;

    struct CountOp : public FunctionPass {
        map<string, int> opCounter;
        static char ID;

        CountOp() : FunctionPass(ID) {}

        bool runOnFunction(Function &F) override {
            errs() << "In Function " << F.getName() << '\n';
            for (auto & basicBlock : F) {
                for (auto & instruction : basicBlock) {
                    if (auto opname = instruction.getOpcodeName(); opCounter.find(opname) == opCounter.end()) {
                        opCounter[opname] = 1;
                    } else {
                        opCounter[opname]++;
                    }
                }
            }

            for (auto&[opname, count] : opCounter) {
                errs() << opname <<": " << count  << '\n';
            }
            errs() << "Function ended.\n\n";
            opCounter.clear();
            return false;
        }
    };
}

char CountOp::ID = 0;
static RegisterPass<CountOp> X("opCounter", "Counts opcodes per function");